import json
import sys

import requests
from loguru import logger

# set log level
logger.remove()
logger.add(sys.stdout, level='INFO')


def parse_token(text):
    _start_template = '"access_token":"'
    _end_template = '"'
    start_idx = text.find(_start_template) + len(_start_template)
    end_idx = text.find(_end_template, start_idx)

    return text[start_idx:end_idx]


class LinkedCareClient:
    _headers = {'content-type': "application/json"}

    def __init__(self, login):
        self.login(login)
        pass

    def login(self, body):
        # 鉴权
        url = 'https://hljkq.linkedcare.cn/LogOn'
        response = requests.post(url, data=json.dumps(body), headers=self._headers)
        authorization = 'bearer ' + parse_token(response.headers['Set-Cookie'])
        logger.info('token: %s' % authorization)
        self._headers['authorization'] = authorization

    def search(self, page_index=1, page_size=20):
        url = 'https://api-hz01.linkedcare.cn:9001/api/v3/patient/search'
        body = {
            "isMyPatientOnly": False,
            "isHealthCheckOnly": False,
            "pageIndex": page_index,
            "pageSize": page_size,
            "searchConfig": {
                "id": 0,
                "groupType": 0,
                "searchType": "患者查询",
                "name": "全部患者",
                "userId": 5795,
                "isShowWeiXin": False,
                "isAscending": False,
                "orderByField": "p.Id",
                "searchResultFields": [
                    {
                        "code": "Name"
                    },
                    {
                        "code": "Mobile"
                    },
                    {
                        "code": "PrivateId"
                    },
                    {
                        "code": "Age"
                    },
                    {
                        "code": "Sex"
                    },
                    {
                        "code": "PatientType"
                    },
                    {
                        "code": "Birth"
                    },
                    {
                        "code": "PhoneNumber"
                    },
                    {
                        "code": "OfficeName"
                    },
                    {
                        "code": "Source"
                    },
                    {
                        "code": "MembershipTypeName"
                    },
                    {
                        "code": "RecordCreatedTime"
                    },
                    {
                        "code": "RecordCreatedUserName"
                    },
                    {
                        "code": "OnlineConsultantName"
                    },
                    {
                        "code": "Point"
                    },
                    {
                        "code": "HasAppointment"
                    },
                    {
                        "code": "VisitCnt"
                    },
                    {
                        "code": "IsDealt"
                    },
                    {
                        "code": "FirstVisit"
                    },
                    {
                        "code": "ChiefComplaint"
                    },
                    {
                        "code": "PatientConsultItem"
                    },
                    {
                        "code": "DoctorName"
                    },
                    {
                        "code": "LastVisit"
                    },
                    {
                        "code": "LastDoctorName"
                    },
                    {
                        "code": "WxBound"
                    },
                    {
                        "code": "IsWxWorkBound"
                    },
                    {
                        "code": "Notes"
                    },
                    {
                        "code": "TotalAmount"
                    },
                    {
                        "code": "ConsultantId"
                    },
                    {
                        "code": "Nationality"
                    },
                    {
                        "code": "PatientTag"
                    },
                    {
                        "code": "HomeAddress"
                    },
                    {
                        "code": "AddressContent"
                    },
                    {
                        "code": "DeveloperName"
                    },
                    {
                        "code": "DutyDoctorName"
                    },
                    {
                        "code": "AttendantName"
                    },
                    {
                        "code": "Job"
                    },
                    {
                        "code": "Field1"
                    },
                    {
                        "code": "Field10"
                    },
                    {
                        "code": "Oper"
                    },
                    {
                        "code": "Mobile"
                    },
                    {
                        "code": "Age"
                    },
                    {
                        "code": "Sex"
                    },
                    {
                        "code": "Name"
                    },
                    {
                        "code": "PrivateId"
                    },
                    {
                        "code": "SourceType"
                    }
                ]
            },
            "searchFilters": []
        }

        response = requests.post(url, data=json.dumps(body), headers=self._headers)
        logger.trace('search: %s' % json.dumps(response.json()))

        items = response.json()['items']
        is_end = len(items) == 0
        return items, is_end

    def search_text(self, text, page_index=1, page_size=10):
        url = 'https://api-hz01.linkedcare.cn:9001/api/v1/patients'
        params = {
            'pageIndex': page_index,
            'pageSize': page_size,
            'searchString': text
        }

        response = requests.get(url, headers=self._headers, params=params)
        logger.trace('search: %s' % json.dumps(response.json()))

        items = response.json()['items']
        is_end = len(items) == 0

        logger.info('读取到共【%d】条数据' % len(items))
        return items, is_end

    def head_info(self, patient_ids):
        url = 'https://api-hz01.linkedcare.cn:9001/api/v1/patients/head-info/'
        body = {
            "patientIds": patient_ids
        }

        response = requests.post(url, data=json.dumps(body), headers=self._headers)
        logger.trace('head_info: %s' % json.dumps(response.json()))

    def search_with_images(self, patient_id):
        url = 'https://api-hz01.linkedcare.cn:9001/api/v1/appointments/search-with-images?patientId=' + str(patient_id)

        response = requests.get(url, headers=self._headers)
        logger.trace('search_with_images: %s' % json.dumps(response.json()))

        images = []
        for item in response.json():
            if item['images'] is not None:
                for image in item['images']:
                    images.append(image)
        logger.info('查找到【%d】条影像数据' % len(images))
        return images

    def image_export(self, patient_name, patient_private_id, images):
        url = 'https://api-hz01.linkedcare.cn:9201/api/v1/image-export'
        body = {
            'patientName': patient_name,
            'patientPrivateId': patient_private_id,
            'images': images
        }
        try:
            logger.info('开始打包影像数据【%s_%s】，请稍后。' % (patient_name, patient_private_id))

            for retry in range(5):
                response = requests.post(url, data=json.dumps(body), headers=self._headers)
                # TODO: 重试机制
                if response.status_code != 200:
                    logger.error('status_code != 200, 准备重试')
                    continue
                if '504 Gateway Time-out' in response.text:
                    logger.error('504 Gateway Time-out, 准备重试')
                    continue
                logger.trace('image_export: %s' % json.dumps(response.json()))
                return response.json()
        except Exception as e:
            logger.error('response: ' + response.text)
            logger.error(e)
        return None
